package com.neusoft.hifly.security;

import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;

/**
 * DES安全编码组件
 *
 * <pre>
 * 支持 DES、DESede(TripleDES,就是3DES)、AES、Blowfish、RC2、RC4(ARCFOUR)
 * DES          		key size must be equal to 56
 * DESede(TripleDES) 	key size must be equal to 112 or 168
 * AES          		key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
 * Blowfish     		key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
 * RC2          		key size must be between 40 and 1024 bits
 * RC4(ARCFOUR) 		key size must be between 40 and 1024 bits
 * 具体内容 需要关注 JDK Document http://.../docs/technotes/guides/security/SunProviders.html
 * </pre>
 */
public final class DESCoder {
	/**
	 * ALGORITHM 算法 <br>
	 * 可替换为以下任意一种算法，同时key值的size相应改变。
	 *
	 * <pre>
	 * DES          		key size must be equal to 56	比较容易被破解
	 * DESede(TripleDES) 	key size must be equal to 112 or 168
	 * AES          		key size must be equal to 128, 192 or 256,but 192 and 256 bits may not be available
	 * Blowfish     		key size must be multiple of 8, and can only range from 32 to 448 (inclusive)
	 * RC2          		key size must be between 40 and 1024 bits
	 * RC4(ARCFOUR) 		key size must be between 40 and 1024 bits
	 * </pre>
	 *
	 * 在Key toKey(byte[] key)方法中使用下述代码 <code>SecretKey secretKey = new SecretKeySpec(key, ALGORITHM);</code> 替换 <code>
	 * DESKeySpec dks = new DESKeySpec(key);
	 * SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
	 * SecretKey secretKey = keyFactory.generateSecret(dks);
	 * </code>
	 */
	private static final String ALGORITHM = "DES";
	/**
	 * 密钥长度
	 */
	private static final int KEYSIZE = 56;

	/**
	 * 转换密钥<br>
	 *
	 * @param key
	 * @return
	 * @throws Exception
	 */
	private static Key toKey(final byte[] key) {
		//		DESKeySpec dks = new DESKeySpec(key);
		//		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
		//		SecretKey secretKey = keyFactory.generateSecret(dks);
		// 当使用其他对称加密算法时，如AES、Blowfish等算法时，用下述代码替换上述三行代码
		final SecretKey secretKey = new SecretKeySpec(key, DESCoder.ALGORITHM);
		return secretKey;
	}

	/**
	 * 解密
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] decrypt(final byte[] data, final String key) {
		try {
			final Key k = DESCoder.toKey(Base64.decodeBase64(key.getBytes()));
			final Cipher cipher = Cipher.getInstance(DESCoder.ALGORITHM);
			cipher.init(Cipher.DECRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (final NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (final NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (final InvalidKeyException e) {
			e.printStackTrace();
		} catch (final IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (final BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 加密
	 *
	 * @param data
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static byte[] encrypt(final byte[] data, final String key) {
		try {
			final Key k = DESCoder.toKey(Base64.decodeBase64(key.getBytes()));
			final Cipher cipher = Cipher.getInstance(DESCoder.ALGORITHM);
			cipher.init(Cipher.ENCRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (final NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (final NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (final InvalidKeyException e) {
			e.printStackTrace();
		} catch (final IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (final BadPaddingException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 生成密钥
	 *
	 * @return
	 * @throws Exception
	 */
	public static String initKey() {
		return DESCoder.initKey(null);
	}

	/**
	 * 生成密钥
	 *
	 * @param seed
	 * @return
	 * @throws Exception
	 */
	public static String initKey(final String seed) {
		try {
			SecureRandom secureRandom = null;
			if (seed != null) {
				// 每次生成的密钥都一样
				secureRandom = new SecureRandom(Base64.decodeBase64(seed.getBytes()));
			} else {
				secureRandom = new SecureRandom();
			}
			final KeyGenerator kg = KeyGenerator.getInstance(DESCoder.ALGORITHM);
			kg.init(DESCoder.KEYSIZE, secureRandom);
			final SecretKey secretKey = kg.generateKey();
			return new String(Base64.encodeBase64(secretKey.getEncoded()));
		} catch (final NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 测试
	 *
	 * @param args
	 *            参数
	 * @throws Exception
	 *             异常
	 */
	public static void main(final String[] args) throws Exception {
		final String inputStr = "Hellow Word!This is a organ key.这是一段密文";
		final String key = DESCoder.initKey();
		System.err.println("原文:\t" + inputStr);
		System.err.println("密钥:\t" + key);
		byte[] inputData = inputStr.getBytes();
		inputData = DESCoder.encrypt(inputData, key);
		System.err.println("加密后:\t" + new String(Base64.encodeBase64(inputData)));
		final byte[] outputData = DESCoder.decrypt(inputData, key);
		final String outputStr = new String(outputData);
		System.err.println("解密后:\t" + outputStr);

	}
}
